Визуализация наглядно показывает тренды, паттерны и выбросы, которые тяжело увидеть в числах, особенно когда их много
Anscombe's Quartet - работа Anscombe, F. J. (1973). “Graphs in Statistical Analysis”
Эти 4 набора данных имеют одинаковые статистические свойства, но на самом деле распределены сильно по-разному

Другой пример - Datasaurus Dozen (Justin Matejka, George Fitzmaurice, Alberto Cairo)

%matplotlib inline
%load_ext autoreload
%autoreload 2
from IPython.core.display import display, HTML
display(HTML("<style>.container { width:95% !important; }</style>"))
Выбор графика начинается с определения задачи: хотим ли мы
Специально для seaborn

import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib
from matplotlib import pyplot as plt
%matplotlib inline
%config InlineBackend.figure_format='retina'
import warnings
warnings.filterwarnings("ignore")
pd.__version__, np.__version__, sns.__version__, matplotlib.__version__
('2.0.3', '1.24.4', '0.13.0', '3.7.3')
penguins = sns.load_dataset('penguins')
penguins
| species | island | bill_length_mm | bill_depth_mm | flipper_length_mm | body_mass_g | sex | |
|---|---|---|---|---|---|---|---|
| 0 | Adelie | Torgersen | 39.1 | 18.7 | 181.0 | 3750.0 | Male |
| 1 | Adelie | Torgersen | 39.5 | 17.4 | 186.0 | 3800.0 | Female |
| 2 | Adelie | Torgersen | 40.3 | 18.0 | 195.0 | 3250.0 | Female |
| 3 | Adelie | Torgersen | NaN | NaN | NaN | NaN | NaN |
| 4 | Adelie | Torgersen | 36.7 | 19.3 | 193.0 | 3450.0 | Female |
| ... | ... | ... | ... | ... | ... | ... | ... |
| 339 | Gentoo | Biscoe | NaN | NaN | NaN | NaN | NaN |
| 340 | Gentoo | Biscoe | 46.8 | 14.3 | 215.0 | 4850.0 | Female |
| 341 | Gentoo | Biscoe | 50.4 | 15.7 | 222.0 | 5750.0 | Male |
| 342 | Gentoo | Biscoe | 45.2 | 14.8 | 212.0 | 5200.0 | Female |
| 343 | Gentoo | Biscoe | 49.9 | 16.1 | 213.0 | 5400.0 | Male |
344 rows × 7 columns
plt.figure(figsize=(15, 5))
plt.subplot(1, 3, 1)
sns.histplot(penguins, x='bill_depth_mm')
plt.subplot(1, 3, 2)
sns.histplot(penguins, x='bill_depth_mm', bins=50)
plt.subplot(1, 3, 3)
sns.histplot(penguins, x='bill_depth_mm', binwidth=100)
plt.show()
order=penguins["species"].value_counts()
order
Adelie 152 Gentoo 124 Chinstrap 68 Name: species, dtype: int64
order.index
Index(['Adelie', 'Gentoo', 'Chinstrap'], dtype='object')
penguins["species"]
0 Adelie
1 Adelie
2 Adelie
3 Adelie
4 Adelie
...
339 Gentoo
340 Gentoo
341 Gentoo
342 Gentoo
343 Gentoo
Name: species, Length: 344, dtype: object
ax = sns.countplot(x=penguins["species"], order=penguins["species"].value_counts().index)
# подписи значений для каждого столбика
for p in ax.patches:
percentage ='1' + 'M'
width, height =p.get_width(),p.get_height()
x=p.get_x() + width - 0.5
y=p.get_y() + height / 2 + 0.15
ax.annotate(percentage,(x,y))
plt.title('Top-20 Countries by Population', fontsize=16);
#sns.despine() # убираем верхнюю и правую рамки
ax.tick_params(left=False)
sns.despine()
plt.show()
Барчарт с группировкой если хотим увидеть подробности внутри классов
sns.countplot(data=penguins, x="species", hue='sex', order=penguins["species"].value_counts().index)
plt.show()
Барчарт с накоплением. В таком случае сравнивать лучше всего получается только нижнюю часть
peng_m = penguins[penguins['sex'] == 'Male']
peng_f = penguins[penguins['sex'] == 'Female']
plt.bar(peng_m['island'].unique(), peng_m['island'].value_counts());
plt.bar(peng_f['island'].unique(), peng_f['island'].value_counts(), bottom = peng_m['island'].value_counts());
peng_pc
island species
Biscoe Adelie 0.269939
Gentoo 0.730061
Dream Adelie 0.447154
Chinstrap 0.552846
Torgersen Adelie 1.000000
Name: sex, dtype: float64
peng_pc.unstack()
| species | Adelie | Chinstrap | Gentoo |
|---|---|---|---|
| island | |||
| Biscoe | 0.269939 | NaN | 0.730061 |
| Dream | 0.447154 | 0.552846 | NaN |
| Torgersen | 1.000000 | NaN | NaN |
# С долями (Stacked Percentage Bar Plot)
peng_pc = penguins.groupby(['island', 'species'])['sex'].count()/penguins.groupby(['island'])['sex'].count()
# pd.DataFrame(peng_pc)
ax = peng_pc.unstack().plot(kind = 'bar', stacked=True, title='Share of each species on the island', width = 0.8)
plt.legend(bbox_to_anchor=(1, 1), loc='upper left')
for p in ax.patches:
width, height =p.get_width(), p.get_height()
if height == 0.00:
continue
percentage = f'{height:.2f}'
x = p.get_x() + width / 2 - 0.15
y = p.get_y() + height / 2
ax.annotate(percentage,(x,y), fontsize=15)
plt.xticks(rotation=0)
print(dir(ax))
ax.set_yticks([])
sns.despine()
plt.show()
['ArtistList', '_PROPERTIES_EXCLUDED_FROM_SET', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getstate__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setstate__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_add_text', '_adjustable', '_agg_filter', '_alias_map', '_alpha', '_anchor', '_animated', '_aspect', '_autoscaleXon', '_autoscaleYon', '_autotitlepos', '_axes', '_axes_class', '_axes_locator', '_axis_names', '_axisbelow', '_box_aspect', '_callbacks', '_check_no_units', '_children', '_clipon', '_clippath', '_cm_set', '_colorbars', '_convert_dx', '_current_image', '_default_contains', '_deprecate_noninstance', '_facecolor', '_fill_between_x_or_y', '_frameon', '_gci', '_gen_axes_patch', '_gen_axes_spines', '_get_axis_list', '_get_axis_map', '_get_clipping_extent_bbox', '_get_lines', '_get_pan_points', '_get_patches_for_fill', '_get_view', '_gid', '_gridOn', '_in_layout', '_init_axis', '_label', '_label_outer_xaxis', '_label_outer_yaxis', '_left_title', '_make_twin_axes', '_mouseover', '_mouseover_set', '_navigate', '_navigate_mode', '_originalPosition', '_parse_scatter_color_args', '_path_effects', '_pcolor_grid_deprecation_helper', '_pcolorargs', '_picker', '_position', '_prepare_view_from_bbox', '_process_unit_info', '_projection_init', '_quiver_units', '_rasterization_zorder', '_rasterized', '_remove_legend', '_remove_method', '_request_autoscale_view', '_right_title', '_sci', '_set_alpha_for_array', '_set_artist_props', '_set_gc_clip', '_set_lim_and_transforms', '_set_position', '_set_title_offset_trans', '_set_view', '_set_view_from_bbox', '_shared_axes', '_sharex', '_sharey', '_sketch', '_snap', '_stale', '_stale_viewlims', '_sticky_edges', '_subplotspec', '_tight', '_transform', '_transformSet', '_twinned_axes', '_unit_change_handler', '_unstale_viewLim', '_update_image_limits', '_update_line_limits', '_update_patch_limits', '_update_set_signature_and_docstring', '_update_title_position', '_update_transScale', '_url', '_use_sticky_edges', '_validate_converted_limits', '_viewLim', '_visible', '_xaxis_transform', '_xmargin', '_yaxis_transform', '_ymargin', 'acorr', 'add_artist', 'add_callback', 'add_child_axes', 'add_collection', 'add_container', 'add_image', 'add_line', 'add_patch', 'add_table', 'angle_spectrum', 'annotate', 'apply_aspect', 'arrow', 'artists', 'autoscale', 'autoscale_view', 'axes', 'axhline', 'axhspan', 'axis', 'axison', 'axline', 'axvline', 'axvspan', 'bar', 'bar_label', 'barbs', 'barh', 'bbox', 'boxplot', 'broken_barh', 'bxp', 'callbacks', 'can_pan', 'can_zoom', 'change_geometry', 'child_axes', 'cla', 'clabel', 'clear', 'clipbox', 'cohere', 'collections', 'containers', 'contains', 'contains_point', 'contour', 'contourf', 'convert_xunits', 'convert_yunits', 'csd', 'dataLim', 'drag_pan', 'draw', 'draw_artist', 'end_pan', 'errorbar', 'eventplot', 'figbox', 'figure', 'fill', 'fill_between', 'fill_betweenx', 'findobj', 'fmt_xdata', 'fmt_ydata', 'format_coord', 'format_cursor_data', 'format_xdata', 'format_ydata', 'get_adjustable', 'get_agg_filter', 'get_alpha', 'get_anchor', 'get_animated', 'get_aspect', 'get_autoscale_on', 'get_autoscalex_on', 'get_autoscaley_on', 'get_axes_locator', 'get_axisbelow', 'get_box_aspect', 'get_children', 'get_clip_box', 'get_clip_on', 'get_clip_path', 'get_cursor_data', 'get_data_ratio', 'get_default_bbox_extra_artists', 'get_facecolor', 'get_fc', 'get_figure', 'get_frame_on', 'get_geometry', 'get_gid', 'get_gridspec', 'get_images', 'get_in_layout', 'get_label', 'get_legend', 'get_legend_handles_labels', 'get_lines', 'get_navigate', 'get_navigate_mode', 'get_path_effects', 'get_picker', 'get_position', 'get_rasterization_zorder', 'get_rasterized', 'get_renderer_cache', 'get_shared_x_axes', 'get_shared_y_axes', 'get_sketch_params', 'get_snap', 'get_subplotspec', 'get_tightbbox', 'get_title', 'get_transform', 'get_transformed_clip_path_and_affine', 'get_url', 'get_visible', 'get_window_extent', 'get_xaxis', 'get_xaxis_text1_transform', 'get_xaxis_text2_transform', 'get_xaxis_transform', 'get_xbound', 'get_xgridlines', 'get_xlabel', 'get_xlim', 'get_xmajorticklabels', 'get_xminorticklabels', 'get_xscale', 'get_xticklabels', 'get_xticklines', 'get_xticks', 'get_yaxis', 'get_yaxis_text1_transform', 'get_yaxis_text2_transform', 'get_yaxis_transform', 'get_ybound', 'get_ygridlines', 'get_ylabel', 'get_ylim', 'get_ymajorticklabels', 'get_yminorticklabels', 'get_yscale', 'get_yticklabels', 'get_yticklines', 'get_yticks', 'get_zorder', 'grid', 'has_data', 'have_units', 'hexbin', 'hist', 'hist2d', 'hlines', 'ignore_existing_data_limits', 'images', 'imshow', 'in_axes', 'indicate_inset', 'indicate_inset_zoom', 'inset_axes', 'invert_xaxis', 'invert_yaxis', 'is_first_col', 'is_first_row', 'is_last_col', 'is_last_row', 'is_transform_set', 'label_outer', 'legend', 'legend_', 'lines', 'locator_params', 'loglog', 'magnitude_spectrum', 'margins', 'matshow', 'minorticks_off', 'minorticks_on', 'mouseover', 'name', 'numCols', 'numRows', 'patch', 'patches', 'pchanged', 'pcolor', 'pcolorfast', 'pcolormesh', 'phase_spectrum', 'pick', 'pickable', 'pie', 'plot', 'plot_date', 'properties', 'psd', 'quiver', 'quiverkey', 'redraw_in_frame', 'relim', 'remove', 'remove_callback', 'reset_position', 'scatter', 'secondary_xaxis', 'secondary_yaxis', 'semilogx', 'semilogy', 'set', 'set_adjustable', 'set_agg_filter', 'set_alpha', 'set_anchor', 'set_animated', 'set_aspect', 'set_autoscale_on', 'set_autoscalex_on', 'set_autoscaley_on', 'set_axes_locator', 'set_axis_off', 'set_axis_on', 'set_axisbelow', 'set_box_aspect', 'set_clip_box', 'set_clip_on', 'set_clip_path', 'set_facecolor', 'set_fc', 'set_figure', 'set_frame_on', 'set_gid', 'set_in_layout', 'set_label', 'set_navigate', 'set_navigate_mode', 'set_path_effects', 'set_picker', 'set_position', 'set_prop_cycle', 'set_rasterization_zorder', 'set_rasterized', 'set_sketch_params', 'set_snap', 'set_subplotspec', 'set_title', 'set_transform', 'set_url', 'set_visible', 'set_xbound', 'set_xlabel', 'set_xlim', 'set_xmargin', 'set_xscale', 'set_xticklabels', 'set_xticks', 'set_ybound', 'set_ylabel', 'set_ylim', 'set_ymargin', 'set_yscale', 'set_yticklabels', 'set_yticks', 'set_zorder', 'sharex', 'sharey', 'specgram', 'spines', 'spy', 'stackplot', 'stairs', 'stale', 'stale_callback', 'start_pan', 'stem', 'step', 'sticky_edges', 'streamplot', 'table', 'tables', 'text', 'texts', 'tick_params', 'ticklabel_format', 'title', 'titleOffsetTrans', 'transAxes', 'transData', 'transLimits', 'transScale', 'tricontour', 'tricontourf', 'tripcolor', 'triplot', 'twinx', 'twiny', 'update', 'update_datalim', 'update_from', 'update_params', 'use_sticky_edges', 'viewLim', 'violin', 'violinplot', 'vlines', 'xaxis', 'xaxis_date', 'xaxis_inverted', 'xcorr', 'yaxis', 'yaxis_date', 'yaxis_inverted', 'zorder']
Показывает статистические свойства по категориям - медиана, 25 и 75 квартили, минимум, максимум и выбросы.
sns.boxplot(data=penguins, x='species', y='body_mass_g')
plt.show()
Показывает почти всё то же, что боксплот, но ещё и форму распределения
sns.violinplot(data=penguins, x='species', y='body_mass_g')
plt.show()
Показывает форму распределения со сглаживанием
sns.kdeplot(penguins['bill_depth_mm'], cut=0)
#sns.distplot(penguins['bill_depth_mm'])
#sns.displot(penguins['bill_depth_mm'], kde=True, bins=30)
#sns.histplot(penguins['bill_depth_mm'], kde=True, bins=30) # kde можно подключить сразу к гистограмме
plt.show()
sns.kdeplot(data=penguins, x='bill_depth_mm', hue='species')
plt.show()
С гистограммой такое провернуть сложнее
sns.histplot(data=penguins, x='bill_depth_mm', hue='species')
plt.show()
Показывает отношение между двумя переменными
sns.scatterplot(data=penguins, x='body_mass_g', y='bill_length_mm', hue='species')
plt.show()
# чтобы увидеть линию регрессии
sns.lmplot(data=penguins, x='body_mass_g', y='bill_length_mm')
plt.show()
# sns.regplot(data=penguins, x='body_mass_g', y='bill_length_mm')
sns.jointplot(x="bill_length_mm",
y="bill_depth_mm",
data=penguins,
hue='species')
plt.show()
Величина показывается цветом. Удобна для изображения коэффициентов корреляции.
corr = penguins.corr()
corr
| bill_length_mm | bill_depth_mm | flipper_length_mm | body_mass_g | |
|---|---|---|---|---|
| bill_length_mm | 1.000000 | -0.235053 | 0.656181 | 0.595110 |
| bill_depth_mm | -0.235053 | 1.000000 | -0.583851 | -0.471916 |
| flipper_length_mm | 0.656181 | -0.583851 | 1.000000 | 0.871202 |
| body_mass_g | 0.595110 | -0.471916 | 0.871202 | 1.000000 |
sns.heatmap(corr)
plt.show()
Для более точной визуализации можно сделать шкалу от -1 до 1, выбрать расходящуюся (diverging) цветовую схему, показать точные значения в ячейках и можно убрать повторяющуюся верхнюю часть
mask = np.zeros_like(corr)
mask[np.triu_indices_from(mask)] = True
sns.heatmap(corr, annot=True, mask=mask, vmin=-1, vmax=1, cmap='PuOr_r', cbar=True, square=True)
plt.show()
И совсем не удобна для категорий, потому что концепция классов и соединяющие линии противоречат
flights = sns.load_dataset('flights')
flights
| year | month | passengers | |
|---|---|---|---|
| 0 | 1949 | Jan | 112 |
| 1 | 1949 | Feb | 118 |
| 2 | 1949 | Mar | 132 |
| 3 | 1949 | Apr | 129 |
| 4 | 1949 | May | 121 |
| ... | ... | ... | ... |
| 139 | 1960 | Aug | 606 |
| 140 | 1960 | Sep | 508 |
| 141 | 1960 | Oct | 461 |
| 142 | 1960 | Nov | 390 |
| 143 | 1960 | Dec | 432 |
144 rows × 3 columns
sns.lineplot(data=flights.groupby('month').mean(), x='month', y='passengers')
plt.show()
pas = flights.groupby('year')['passengers'].sum()
sns.lineplot(data=pas, x='year', y=pas.values)
plt.show()
Показывает доли категорий от всей выборки. Чаще всего не лучший выбор и заменяется барплотом, потому что формы сравнивать сложно.
plt.pie(penguins['species'].value_counts(), startangle=90, autopct='%1.f%%')
plt.legend(labels=penguins['species'].value_counts().index, loc='lower left')
plt.show()
sns.pairplot(data=penguins)
plt.show()
# верхняя часть повторяет нижнюю, поэтому её имеет смысл убрать
sns.pairplot(data=penguins, hue='species', corner = True)
plt.show()
sns.pairplot(data=penguins, hue='species', kind='hist', corner = True)
plt.show()
# по какому столбцу бьем, разбиение
g = sns.FacetGrid(penguins, col="sex", hue="species")
g.map(sns.scatterplot, "bill_length_mm", "flipper_length_mm")
# plt.legend()
plt.show()
g = sns.FacetGrid(penguins, col="species")
g.map(sns.histplot, "bill_length_mm")
# g.map(sns.histplot, "flipper_length_mm")
plt.show()
Subplots
fig, axes = plt.subplots(1, 4, figsize=(17, 4))
fig, axes = plt.subplots(1, 4, figsize=(19, 4))
sns.violinplot(ax=axes[0], data=penguins, x='species', y='flipper_length_mm')
sns.violinplot(ax=axes[1], data=penguins, x='species', y='bill_length_mm')
sns.barplot(ax=axes[2], data=penguins, x='species', y='bill_depth_mm', estimator=np.median)
sns.boxplot(ax=axes[3], data=penguins, x='species', y='body_mass_g')
fig.suptitle('Distribution of characteristics by species', fontsize=16);
# plt.subplots_adjust(right=1.1)
plt.savefig('./jgpasgjas.jpg')
fig, axes = plt.subplots(4, 3, figsize=(18, 18), sharey = True)
ro = 0
co = 0
for i in penguins.columns[2:6]:
for j in penguins['species'].unique():
sns.histplot(data=penguins[penguins['species'] == j][i], ax=axes[ro, co], kde=True)
if ro==0:
axes[ro, co].set_title(j, pad=2, fontsize=20)
co+=1
if co>=3:
co=0
ro+=1
colors = {'Adelie': "#FC3F1D", 'Chinstrap': "#7cec84", 'Gentoo': "#1E1E1E"} #1E1E1E
order = penguins["species"].value_counts().index
order
Index(['Adelie', 'Gentoo', 'Chinstrap'], dtype='object')
colors
{'Adelie': '#FC3F1D', 'Chinstrap': '#7cec84', 'Gentoo': '#1E1E1E'}
sns.countplot(x=penguins["species"], order=order, palette=colors)
plt.show()
sns.countplot(x=penguins["species"], order=order, palette=colors)
plt.show()
нехорошо, если на разных графиках в одном проекте одни и те же классы показывают разными цветами/формами. Классы должны оставаться узнаваемыми от графика к графику
vorder = penguins.groupby('species').median()['body_mass_g'].sort_values(ascending=False).index
vorder
Index(['Gentoo', 'Adelie', 'Chinstrap'], dtype='object', name='species')
sns.violinplot(data=penguins, x='species', y='body_mass_g', palette=colors, order=vorder)
plt.show()
sns.kdeplot(data=penguins, x='body_mass_g', hue='species', palette=colors)
plt.show()
sns.histplot(data=penguins, x='body_mass_g', hue='species', palette=colors)
plt.show()
sns.pairplot(data=penguins, hue='species', corner=True, palette=colors)
plt.show()
# Странненько. Пугает.
g = sns.lineplot(data=flights.groupby('year')['passengers'].sum(),
y='year',
x=flights.groupby('year')['passengers'].sum().values)
xlabels = ['{:d}'.format(int(x)) + 'K' for x in g.get_xticks()/1000]
g.set_xticklabels(xlabels)
sns.despine()
Названия, подписи осей, легенда, источник данных, пояснения
sns.despine()
10000, 20000, 50000, 550000 удобно записать как 10K, 20K, 50K, 550K
Повторяющиеся оси на нескольких типовых графиках можно показать один раз
3D эффекты, тени, градиенты в заливке графика и фона, частые или яркие линии сетки создают лишний шум
sns.color_palette("bright", 9)
sns.color_palette("mako", 9)
sns.color_palette("vlag", 9)
Радужная цветовая схема обладает смешанными свойствами - одновременно категориальными и непрерывными
Непостоянная яркость - желтый и голубой утягивают внимание
Даже при использовании для категорий переходы резкие
Для более справедливого использования разработаны специальные равномерные схемы - viridis, inferno, plasma ...
Тем не менее, иногда она лучше передаёт детали

sns.color_palette("rainbow", 9)
sns.color_palette("viridis", 9)
sns.color_palette("plasma", 9)
sns.color_palette("magma", 9)
Если мы пытаемся нарисовать слишком много категорий - больше, чем в текущей палитре - seaborn присваивает им круговую схему
sns.color_palette("husl", 15)
Идеально - около 5, но больше 7 уже нехорошо. Можно группировать категории, чтобы их стало поменьше.
# https://www.kaggle.com/fernandol/countries-of-the-world?select=countries+of+the+world.csv
w = pd.read_csv('countries of the world.csv')
w
| Country | Region | Population | Area (sq. mi.) | Pop. Density (per sq. mi.) | Coastline (coast/area ratio) | Net migration | Infant mortality (per 1000 births) | GDP ($ per capita) | Literacy (%) | Phones (per 1000) | Arable (%) | Crops (%) | Other (%) | Climate | Birthrate | Deathrate | Agriculture | Industry | Service | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | Afghanistan | ASIA (EX. NEAR EAST) | 31056997 | 647500 | 48,0 | 0,00 | 23,06 | 163,07 | 700.0 | 36,0 | 3,2 | 12,13 | 0,22 | 87,65 | 1 | 46,6 | 20,34 | 0,38 | 0,24 | 0,38 |
| 1 | Albania | EASTERN EUROPE | 3581655 | 28748 | 124,6 | 1,26 | -4,93 | 21,52 | 4500.0 | 86,5 | 71,2 | 21,09 | 4,42 | 74,49 | 3 | 15,11 | 5,22 | 0,232 | 0,188 | 0,579 |
| 2 | Algeria | NORTHERN AFRICA | 32930091 | 2381740 | 13,8 | 0,04 | -0,39 | 31 | 6000.0 | 70,0 | 78,1 | 3,22 | 0,25 | 96,53 | 1 | 17,14 | 4,61 | 0,101 | 0,6 | 0,298 |
| 3 | American Samoa | OCEANIA | 57794 | 199 | 290,4 | 58,29 | -20,71 | 9,27 | 8000.0 | 97,0 | 259,5 | 10 | 15 | 75 | 2 | 22,46 | 3,27 | NaN | NaN | NaN |
| 4 | Andorra | WESTERN EUROPE | 71201 | 468 | 152,1 | 0,00 | 6,6 | 4,05 | 19000.0 | 100,0 | 497,2 | 2,22 | 0 | 97,78 | 3 | 8,71 | 6,25 | NaN | NaN | NaN |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 222 | West Bank | NEAR EAST | 2460492 | 5860 | 419,9 | 0,00 | 2,98 | 19,62 | 800.0 | NaN | 145,2 | 16,9 | 18,97 | 64,13 | 3 | 31,67 | 3,92 | 0,09 | 0,28 | 0,63 |
| 223 | Western Sahara | NORTHERN AFRICA | 273008 | 266000 | 1,0 | 0,42 | NaN | NaN | NaN | NaN | NaN | 0,02 | 0 | 99,98 | 1 | NaN | NaN | NaN | NaN | 0,4 |
| 224 | Yemen | NEAR EAST | 21456188 | 527970 | 40,6 | 0,36 | 0 | 61,5 | 800.0 | 50,2 | 37,2 | 2,78 | 0,24 | 96,98 | 1 | 42,89 | 8,3 | 0,135 | 0,472 | 0,393 |
| 225 | Zambia | SUB-SAHARAN AFRICA | 11502010 | 752614 | 15,3 | 0,00 | 0 | 88,29 | 800.0 | 80,6 | 8,2 | 7,08 | 0,03 | 92,9 | 2 | 41 | 19,93 | 0,22 | 0,29 | 0,489 |
| 226 | Zimbabwe | SUB-SAHARAN AFRICA | 12236805 | 390580 | 31,3 | 0,00 | 0 | 67,69 | 1900.0 | 90,7 | 26,8 | 8,32 | 0,34 | 91,34 | 2 | 28,01 | 21,84 | 0,179 | 0,243 | 0,579 |
227 rows × 20 columns
# w.dtypes
w_num = w.copy()
for i in w_num.columns[4:8].tolist() + w_num.columns[9:14].tolist() + w_num.columns[15:20].tolist():
print(i)
w_num[i] = w_num[i].str.replace(',', '.')
w_num[i] = w_num[i].astype(float)
Pop. Density (per sq. mi.) Coastline (coast/area ratio) Net migration Infant mortality (per 1000 births) Literacy (%) Phones (per 1000) Arable (%) Crops (%) Other (%) Birthrate Deathrate Agriculture Industry Service
# первая попытка
plt.figure(figsize=(10, 30))
ax = sns.barplot(data=w_num,
y='Country', x='Population',
order=w_num['Country'], # по алфавиту
orient='h', hue='Region', dodge=False)
plt.figure(figsize=(10, 30))
ax = sns.barplot(data=w_num.sort_values(by='Population', ascending=False),
y='Country', x='Population',
order=w_num.sort_values(by='Population', ascending=False)['Country'],
orient='h', hue='Region', dodge=False)
# убрать пробелы справа
w_num['Region'] = w_num['Region'].apply(lambda x: x.rstrip())
# объединить регионы
w_num['Region_common'] = w_num['Region'].str.replace('EASTERN EUROPE', 'EUROPE', regex=False)
w_num['Region_common'] = w_num['Region_common'].str.replace('C.W. OF IND. STATES', 'EUROPE', regex=False)
w_num['Region_common'] = w_num['Region_common'].str.replace('WESTERN EUROPE', 'EUROPE', regex=False)
w_num['Region_common'] = w_num['Region_common'].str.replace('BALTICS', 'EUROPE', regex=False)
w_num['Region_common'] = w_num['Region_common'].str.replace('NORTHERN AFRICA', 'AFRICA', regex=False)
w_num['Region_common'] = w_num['Region_common'].str.replace('SUB-SAHARAN AFRICA', 'AFRICA', regex=False)
# w_num['Region'] = w_num['Region'].str.replace('NEAR EAST', 'ASIA', regex=False)
w_num['Region_common'] = w_num['Region_common'].str.replace('ASIA (EX. ASIA)', 'ASIA', regex=False)
w_num['Region_common'].unique()
array(['ASIA (EX. NEAR EAST)', 'EUROPE', 'AFRICA', 'OCEANIA',
'LATIN AMER. & CARIB', 'NEAR EAST', 'NORTHERN AMERICA'],
dtype=object)
w_popdens = w_num[w_num['Pop. Density (per sq. mi.)'] >= 300].sort_values(by='Pop. Density (per sq. mi.)', ascending=False)
# w_pop = w[w['Population'] >= 31000000].sort_values(by='Population', ascending=False)
w_pop = w_num.sort_values(by='Population', ascending=False)[0:21]
w_pop
| Country | Region | Population | Area (sq. mi.) | Pop. Density (per sq. mi.) | Coastline (coast/area ratio) | Net migration | Infant mortality (per 1000 births) | GDP ($ per capita) | Literacy (%) | ... | Arable (%) | Crops (%) | Other (%) | Climate | Birthrate | Deathrate | Agriculture | Industry | Service | Region_common | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 42 | China | ASIA (EX. NEAR EAST) | 1313973713 | 9596960 | 136.9 | 0.15 | -0.40 | 24.18 | 5000.0 | 90.9 | ... | 15.40 | 1.25 | 83.35 | 1,5 | 13.25 | 6.97 | 0.125 | 0.473 | 0.403 | ASIA (EX. NEAR EAST) |
| 94 | India | ASIA (EX. NEAR EAST) | 1095351995 | 3287590 | 333.2 | 0.21 | -0.07 | 56.29 | 2900.0 | 59.5 | ... | 54.40 | 2.74 | 42.86 | 2,5 | 22.01 | 8.18 | 0.186 | 0.276 | 0.538 | ASIA (EX. NEAR EAST) |
| 214 | United States | NORTHERN AMERICA | 298444215 | 9631420 | 31.0 | 0.21 | 3.41 | 6.50 | 37800.0 | 97.0 | ... | 19.13 | 0.22 | 80.65 | 3 | 14.14 | 8.26 | 0.010 | 0.204 | 0.787 | NORTHERN AMERICA |
| 95 | Indonesia | ASIA (EX. NEAR EAST) | 245452739 | 1919440 | 127.9 | 2.85 | 0.00 | 35.60 | 3200.0 | 87.9 | ... | 11.32 | 7.23 | 81.45 | 2 | 20.34 | 6.25 | 0.134 | 0.458 | 0.408 | ASIA (EX. NEAR EAST) |
| 27 | Brazil | LATIN AMER. & CARIB | 188078227 | 8511965 | 22.1 | 0.09 | -0.03 | 29.61 | 7600.0 | 86.4 | ... | 6.96 | 0.90 | 92.15 | 2 | 16.56 | 6.17 | 0.084 | 0.400 | 0.516 | LATIN AMER. & CARIB |
| 156 | Pakistan | ASIA (EX. NEAR EAST) | 165803560 | 803940 | 206.2 | 0.13 | -2.77 | 72.44 | 2100.0 | 45.7 | ... | 27.87 | 0.87 | 71.26 | 1 | 29.74 | 8.23 | 0.216 | 0.251 | 0.533 | ASIA (EX. NEAR EAST) |
| 16 | Bangladesh | ASIA (EX. NEAR EAST) | 147365352 | 144000 | 1023.4 | 0.40 | -0.71 | 62.60 | 1900.0 | 43.1 | ... | 62.11 | 3.07 | 34.82 | 2 | 29.80 | 8.27 | 0.199 | 0.198 | 0.603 | ASIA (EX. NEAR EAST) |
| 169 | Russia | C.W. OF IND. STATES | 142893540 | 17075200 | 8.4 | 0.22 | 1.02 | 15.39 | 8900.0 | 99.6 | ... | 7.33 | 0.11 | 92.56 | NaN | 9.95 | 14.65 | 0.054 | 0.371 | 0.575 | EUROPE |
| 152 | Nigeria | SUB-SAHARAN AFRICA | 131859731 | 923768 | 142.7 | 0.09 | 0.26 | 98.80 | 900.0 | 68.0 | ... | 31.29 | 2.96 | 65.75 | 1,5 | 40.43 | 16.94 | 0.269 | 0.487 | 0.244 | AFRICA |
| 103 | Japan | ASIA (EX. NEAR EAST) | 127463611 | 377835 | 337.4 | 7.87 | 0.00 | 3.26 | 28200.0 | 99.0 | ... | 12.19 | 0.96 | 86.85 | 3 | 9.37 | 9.16 | 0.017 | 0.258 | 0.725 | ASIA (EX. NEAR EAST) |
| 135 | Mexico | LATIN AMER. & CARIB | 107449525 | 1972550 | 54.5 | 0.47 | -4.87 | 20.91 | 9000.0 | 92.2 | ... | 12.99 | 1.31 | 85.70 | 1,5 | 20.69 | 4.74 | 0.038 | 0.259 | 0.702 | LATIN AMER. & CARIB |
| 162 | Philippines | ASIA (EX. NEAR EAST) | 89468677 | 300000 | 298.2 | 12.10 | -1.50 | 23.51 | 4600.0 | 92.6 | ... | 18.95 | 16.77 | 64.28 | 2 | 24.89 | 5.41 | 0.144 | 0.326 | 0.530 | ASIA (EX. NEAR EAST) |
| 219 | Vietnam | ASIA (EX. NEAR EAST) | 84402966 | 329560 | 256.1 | 1.05 | -0.45 | 25.95 | 2500.0 | 90.3 | ... | 19.97 | 5.95 | 74.08 | 2 | 16.86 | 6.22 | 0.209 | 0.410 | 0.381 | ASIA (EX. NEAR EAST) |
| 76 | Germany | WESTERN EUROPE | 82422299 | 357021 | 230.9 | 0.67 | 2.18 | 4.16 | 27600.0 | 99.0 | ... | 33.85 | 0.59 | 65.56 | 3 | 8.25 | 10.62 | 0.009 | 0.296 | 0.695 | EUROPE |
| 60 | Egypt | NORTHERN AFRICA | 78887007 | 1001450 | 78.8 | 0.24 | -0.22 | 32.59 | 4000.0 | 57.7 | ... | 2.87 | 0.48 | 96.65 | 1 | 22.94 | 5.23 | 0.149 | 0.357 | 0.493 | AFRICA |
| 65 | Ethiopia | SUB-SAHARAN AFRICA | 74777981 | 1127127 | 66.3 | 0.00 | 0.00 | 95.32 | 700.0 | 42.7 | ... | 10.71 | 0.75 | 88.54 | 2 | 37.98 | 14.86 | 0.475 | 0.099 | 0.426 | AFRICA |
| 206 | Turkey | NEAR EAST | 70413958 | 780580 | 90.2 | 0.92 | 0.00 | 41.04 | 6700.0 | 86.5 | ... | 30.93 | 3.31 | 65.76 | 3 | 16.62 | 5.97 | 0.117 | 0.298 | 0.585 | NEAR EAST |
| 96 | Iran | ASIA (EX. NEAR EAST) | 68688433 | 1648000 | 41.7 | 0.15 | -0.84 | 41.58 | 7000.0 | 79.4 | ... | 8.72 | 1.39 | 89.89 | 1 | 17.00 | 5.55 | 0.116 | 0.424 | 0.460 | ASIA (EX. NEAR EAST) |
| 201 | Thailand | ASIA (EX. NEAR EAST) | 64631595 | 514000 | 125.7 | 0.63 | 0.00 | 20.48 | 7400.0 | 92.6 | ... | 29.36 | 6.46 | 64.18 | 2 | 13.87 | 7.04 | 0.099 | 0.441 | 0.460 | ASIA (EX. NEAR EAST) |
| 45 | Congo, Dem. Rep. | SUB-SAHARAN AFRICA | 62660551 | 2345410 | 26.7 | 0.00 | 0.00 | 94.69 | 700.0 | 65.5 | ... | 2.96 | 0.52 | 96.52 | 2 | 43.69 | 13.27 | 0.550 | 0.110 | 0.340 | AFRICA |
| 69 | France | WESTERN EUROPE | 60876136 | 547030 | 111.3 | 0.63 | 0.66 | 4.26 | 27600.0 | 99.0 | ... | 33.53 | 2.07 | 64.40 | 4 | 11.99 | 9.14 | 0.022 | 0.214 | 0.764 | EUROPE |
21 rows × 21 columns
muted = sns.color_palette("muted", 20)
muted
colors = {'EUROPE': muted[0],
'AFRICA': 'yellowgreen',
'OCEANIA': muted[9],
'ASIA (EX. NEAR EAST)': muted[3],
'LATIN AMER. & CARIB': 'tab:green',
'NEAR EAST': muted[8],
'NORTHERN AMERICA': muted[5]
}
plt.figure(figsize=(10, 10))
ax = sns.barplot(data=w_pop,
y='Country', x='Population',
order=w_pop['Country'],
orient='h',
hue='Region_common',
dodge=False,
palette=colors)
xlabels = ['{:,.0f}'.format(x/1000000) + 'M' for x in ax.get_xticks()]
ax.set_xticklabels(xlabels);
# подписи значений для каждого столбика
for p in ax.patches:
percentage ='{:,.0f}'.format(p.get_width()/1000000) + 'M'
width, height =p.get_width(),p.get_height()
x=p.get_x()+width+5000000
y=p.get_y()+height/2+0.15
ax.annotate(percentage,(x,y))
plt.title('Top-20 Countries by Population', fontsize=16);
sns.despine() # убираем верхнюю и правую рамки
ax.tick_params(left=False)
plt.figure(figsize=(10, 10))
sns.barplot(data=w_num,
x='Deathrate',
y='Country',
order=w_num.sort_values(by='Deathrate', ascending=False)['Country'][0:51],
hue='Region_common',
dodge=False,
palette=colors)
plt.title('World countries by deathrate', fontsize=16);
Выбирая цвета, хорошо соблюдать принятые нормы и не нарушать привычные ассоциации, например
colors_accent = ['lightgray'] * 7 + ['tab:red'] + ['lightgray'] * 13
plt.figure(figsize=(10, 10))
ax = sns.barplot(data=w_pop,
y='Country', x='Population',
order=w_pop['Country'],
orient='h', dodge=False, palette=colors_accent)
xlabels = ['{:,.0f}'.format(x/1000000) + 'M' for x in ax.get_xticks()]
ax.set_xticklabels(xlabels);
# подписи значений для каждого столбика
for p in ax.patches:
percentage ='{:,.0f}'.format(p.get_width()/1000000) + 'M'
width, height =p.get_width(),p.get_height()
x=p.get_x()+width+5000000
y=p.get_y()+height/2+0.15
ax.annotate(percentage,(x,y))
plt.title('Russia among Top-20 Countries by Population', fontsize=16);
sns.despine() # убираем верхнюю и правую рамки
ax.tick_params(left=False)
https://colorbrewer2.org/#type=sequential&scheme=BuGn&n=3 ColorBrewer
Здесь же можно смотреть коды цветов из многих стандартных палитр
...
# обманные манёвры презента
ab = pd.DataFrame({'col1': ['a', 'b'], 'col2': [113, 110]})
sns.barplot(data=ab, x='col1', y='col2')
ab = pd.DataFrame({'col1': ['a', 'b'], 'col2': [113, 110]})
sns.barplot(data=ab, x='col1', y='col2')
plt.ylim(100, 115)
# внезапные манёвры
sns.regplot(data=w_num, y='Literacy (%)', x=np.log10(w_num['Population']))
plt.tick_params(right=True, top=True, bottom=False, left=False, labelleft=False, labelbottom=False, labelright=True, labeltop=True)
sns.despine(right=False, top=False, bottom=True, left=True)
ab = pd.DataFrame({'col1': ['% positive', '% negative', '% neutral'], 'col2': [11, 8, 5]})
sns.barplot(data=ab, x='col1', y='col2', palette='PuBu')
<AxesSubplot: xlabel='col1', ylabel='col2'>
x1 = np.random.normal(0, 0.5, 10000)
d1 = x1**2 + x1 + np.random.normal(0, 0.5, 10000) + 2
x2 = np.random.normal(0, 0.1, 10000) + 1
d2 = x2**2 + x2 + np.random.normal(0, 0.3, 10000) + 1
x = np.append(x1,x2)
d = np.append(d1,d2)
sns.scatterplot(x, d)
plt.show()
# 1. уменьшить размер точек и увеличить прозрачность
sns.scatterplot(x, d, alpha=0.3, s=0.6, )
plt.show()
# 2. Разновидность тепловой карты
plt.hist2d(x, d, bins=(100, 100), cmap = 'Blues');
plt.colorbar()
plt.show()
sns.jointplot(x=x, y=d, kind='hex', height=6)
plt.show()
xd = pd.concat([pd.Series(x), pd.Series(d)], axis=1)
sns.pairplot(xd, kind="hist", corner=True, diag_kind='kde', height=4)
plt.show()
# 3. Выборка
df = pd.DataFrame({'x':x, 'd':d}).sample(1000)
sns.scatterplot(data=df, x='x', y='d', alpha=0.3, s=4)
plt.show()
Выбросы утягивают на себя шкалы и скрывают остальные значения
# Показать на одном графике общее распределение...
x = np.append(np.random.normal(1, 0.5, 20), [20, 12])
y = np.append(np.random.normal(1, 0.5, 20), [20, 18])
sns.scatterplot(x, y)
plt.show()
# ...и на втором часть без выбросов
xy = pd.DataFrame(columns=['x', 'y'])
xy['x'] = x
xy['y'] = y
def reject_outliers(data, m=2):
return data[abs(data - np.mean(data)) < m * np.std(data)]
sns.scatterplot(x=reject_outliers(xy).x, y=reject_outliers(xy).y)
plt.show()
# Преобразовать шкалу
ax = sns.scatterplot(x, y)
ax.set_xscale('log')
ax.set_yscale('log')
# ~~Подсечь шкалу
# qqplot - для проверки нормальности распределения. Линия из точек хорошо совпадает с диагональю значит, распределение нормальное
from scipy import stats
stats.probplot(w_num['Population'], plot=sns.mpl.pyplot)
stats.probplot(penguins[penguins['species'] == 'Adelie']['flipper_length_mm'], plot=sns.mpl.pyplot)
plt.show()
# Plotly - интерактивные графики
import plotly.express as px
import plotly.graph_objects as go
w_num['GDP ($ per capita)'][223] = 0
colors_px = {'EUROPE': 'steelblue',
'AFRICA': 'yellowgreen',
'OCEANIA': 'skyblue',
'ASIA (EX. NEAR EAST)': 'red',
'LATIN AMER. & CARIB': 'green',
'NEAR EAST': 'orange',
'NORTHERN AMERICA': 'brown'
}
fig = px.scatter(w_num,
y=np.log10(w_num['Population']),
x=np.log10(w_num['Area (sq. mi.)']),
size='GDP ($ per capita)',
color='Region_common',
hover_data=['Country', 'Population', 'Area (sq. mi.)', 'GDP ($ per capita)'],
# color_discrete_sequence=['red', 'steelblue', 'yellowgreen', 'skyblue', 'green', 'orange', 'brown'],
color_discrete_map=colors_px,
title="World Countries Population vs Area"
)
fig.update_layout(
title_y=0.86,
title_x=0.08,
xaxis_title="Log10 Area (sq. mi)",
yaxis_title="Log10 Population",
legend_title="Region",
# font=dict(
# size=13,
# color="darkblue"
# )
)
fig.update_layout(annotations=[
go.layout.Annotation(
showarrow=False,
text='Marker size represents GDP in $ per capita',
x=1.3,
y=9.2,
)])
fig.show()
fig = px.bar(w_num, y="Region_common", x="Population")
fig.update_layout(yaxis={'categoryorder':'total ascending'})
fig.show()
# treemap показывает иерархичные структуры и пропорции в составе групп
w_num["world"] = "world" # создаём общую группу для всех элементов
fig = px.treemap(w_num,
path=['world', 'Region_common', 'Country'],
values='Population',
color='GDP ($ per capita)',
hover_data=['Country', 'GDP ($ per capita)', 'Population'],
color_continuous_scale='OrRd',
title='World Countries Population')
fig.show()
#pip install altair
# altair можно делать и статичные, и интерактивные визуализации
import altair as alt
alt.Chart(w_num).transform_density(
'Deathrate',
as_=['Deathrate', 'density'],
).mark_area(
color='red',opacity=0.3
).encode(
x="Deathrate:Q",
y='density:Q',
)
alt.Chart(flights).mark_rect().encode(
x='year:O',
y=alt.Y('month', sort=['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']),
color='sum(passengers):Q',
tooltip=['passengers']
).properties(
width=300,
height=300
).interactive()
alt.Chart(flights.groupby('month').mean().reset_index()).mark_line(
color='green'
).encode(
x=alt.X('month', sort=['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']),
y=alt.Y('passengers', scale=alt.Scale(zero=False)),
tooltip=['passengers'],
).properties(
width=500,
height=300
).interactive()
#pip install plotnine
# ggplot - пакет для визуализации на R, в питоне пакет называется plotnine
from plotnine import *
w_regcount = w_num['Region'].value_counts().reset_index()
w_regcount.columns = ['region', 'count']
ggorder = w_num['Region'].value_counts().index.tolist()[::-1]
ggplot(data=w_regcount) +\
geom_bar(aes(x='region', y='count'), stat='identity', fill='purple') +\
coord_flip() + scale_x_discrete(limits=ggorder) +\
ggtitle("Count of Countries per Region")
<ggplot: (8789827193561)>
birth = pd.DataFrame(w_num.groupby('Region').mean('Birthrate').sort_values(by='Birthrate', ascending=False)['Birthrate']).reset_index()
b_order = w_num.groupby('Region').mean('Birthrate').sort_values(by='Birthrate', ascending=False).index.tolist()[::-1]
ggplot(birth, aes(x='Region', y='Birthrate')) +\
geom_bar(stat="identity") +\
coord_flip() + scale_x_discrete(limits=b_order) +\
ggtitle("Mean Birthrate per Region")
<ggplot: (8789827874392)>
ggplot(data=w_num) + geom_histogram(aes(x='Birthrate'), fill='steelblue', color='black', bins=50)
<ggplot: (8789826221367)>
ggplot(data=w_num) +\
geom_point(aes(x='GDP ($ per capita)', y='Birthrate', color='Region_common')) +\
scale_color_manual(values=colors_px)
# + scale_x_log10()
<ggplot: (8789826269492)>
w_num
| Country | Region | Population | Area (sq. mi.) | Pop. Density (per sq. mi.) | Coastline (coast/area ratio) | Net migration | Infant mortality (per 1000 births) | GDP ($ per capita) | Literacy (%) | ... | Crops (%) | Other (%) | Climate | Birthrate | Deathrate | Agriculture | Industry | Service | Region_common | world | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | Afghanistan | ASIA (EX. NEAR EAST) | 31056997 | 647500 | 48.0 | 0.00 | 23.06 | 163.07 | 700.0 | 36.0 | ... | 0.22 | 87.65 | 1 | 46.60 | 20.34 | 0.380 | 0.240 | 0.380 | ASIA (EX. NEAR EAST) | world |
| 1 | Albania | EASTERN EUROPE | 3581655 | 28748 | 124.6 | 1.26 | -4.93 | 21.52 | 4500.0 | 86.5 | ... | 4.42 | 74.49 | 3 | 15.11 | 5.22 | 0.232 | 0.188 | 0.579 | EUROPE | world |
| 2 | Algeria | NORTHERN AFRICA | 32930091 | 2381740 | 13.8 | 0.04 | -0.39 | 31.00 | 6000.0 | 70.0 | ... | 0.25 | 96.53 | 1 | 17.14 | 4.61 | 0.101 | 0.600 | 0.298 | AFRICA | world |
| 3 | American Samoa | OCEANIA | 57794 | 199 | 290.4 | 58.29 | -20.71 | 9.27 | 8000.0 | 97.0 | ... | 15.00 | 75.00 | 2 | 22.46 | 3.27 | NaN | NaN | NaN | OCEANIA | world |
| 4 | Andorra | WESTERN EUROPE | 71201 | 468 | 152.1 | 0.00 | 6.60 | 4.05 | 19000.0 | 100.0 | ... | 0.00 | 97.78 | 3 | 8.71 | 6.25 | NaN | NaN | NaN | EUROPE | world |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 222 | West Bank | NEAR EAST | 2460492 | 5860 | 419.9 | 0.00 | 2.98 | 19.62 | 800.0 | NaN | ... | 18.97 | 64.13 | 3 | 31.67 | 3.92 | 0.090 | 0.280 | 0.630 | NEAR EAST | world |
| 223 | Western Sahara | NORTHERN AFRICA | 273008 | 266000 | 1.0 | 0.42 | NaN | NaN | 0.0 | NaN | ... | 0.00 | 99.98 | 1 | NaN | NaN | NaN | NaN | 0.400 | AFRICA | world |
| 224 | Yemen | NEAR EAST | 21456188 | 527970 | 40.6 | 0.36 | 0.00 | 61.50 | 800.0 | 50.2 | ... | 0.24 | 96.98 | 1 | 42.89 | 8.30 | 0.135 | 0.472 | 0.393 | NEAR EAST | world |
| 225 | Zambia | SUB-SAHARAN AFRICA | 11502010 | 752614 | 15.3 | 0.00 | 0.00 | 88.29 | 800.0 | 80.6 | ... | 0.03 | 92.90 | 2 | 41.00 | 19.93 | 0.220 | 0.290 | 0.489 | AFRICA | world |
| 226 | Zimbabwe | SUB-SAHARAN AFRICA | 12236805 | 390580 | 31.3 | 0.00 | 0.00 | 67.69 | 1900.0 | 90.7 | ... | 0.34 | 91.34 | 2 | 28.01 | 21.84 | 0.179 | 0.243 | 0.579 | AFRICA | world |
227 rows × 22 columns
# Как связаны переменные Industry и Birthrate?
sns.regplot(data=w_num, x='Industry', y='Birthrate')
<AxesSubplot: xlabel='Industry', ylabel='Birthrate'>
# Как распределены площади стран мира?
fig = plt.figure(figsize=(7, 5))
sns.histplot(data=w_num, x=np.log10(w_num['Area (sq. mi.)']), bins=30, kde=True)
# plt.xticks(ticks=np.arange(8), labels=[10**i for i in range(8)])
plt.xlabel('Log10 Area')
Text(0.5, 0, 'Log10 Area')
# как скоррелированы переменные датасета?
w_corr = w_num.corr()
fig = plt.figure(figsize=(12, 10))
mask = np.zeros_like(w_corr)
mask[np.triu_indices_from(mask)] = True
sns.heatmap(w_corr, annot=True, mask=mask, vmin=-1, vmax=1, cmap='PuOr_r', cbar=True, square=True, fmt='.2f')
<AxesSubplot: >
# w_log = w_num.copy()
# w_log = w_log.drop(['Infant mortality (per 1000 births)', 'Phones (per 1000)'], axis=1)
# for i in w_log.columns[2:6]:
# w_log[i] = np.log10(w_log[i])
# w_log.isna().sum()
# w_log.replace([np.inf, -np.inf], np.nan, inplace=True)
# sns.pairplot(data=w_log.dropna(), corner=True, kind="reg")
# # plot_kws={'line_kws':{'color':'red'}}
plt.figure(figsize=(10, 10))
sns.scatterplot(data=w_num,
y=np.log10(w_num['Population']),
x=np.log10(w_num['Area (sq. mi.)']),
hue='Region_common',
size='GDP ($ per capita)',
sizes=(10, 500),
alpha=0.8,
palette=colors)
plt.legend(bbox_to_anchor=(1.01, 1), borderaxespad=0, labelspacing=1.2, borderpad=1)
plt.ylabel('log$_{10}$(Population)')
plt.xlabel('log$_{10}$(Area)')
plt.title('Population vs Area', size=16, pad=20);
w_llp = w_num[['Country', 'Deathrate', 'Birthrate', 'Region', 'Region_common']]
w_llp = w_llp.dropna()
w_llp['brth_dth_diff'] = w_llp['Deathrate'] - w_llp['Birthrate'] # разница между рождаемостью и смертностью
w_llp['diff_color'] = ['tab:green' if x < 0 else 'tab:red' for x in w_llp['brth_dth_diff']] # присваиваем значения в виде цвета (можно было 0 и 1)
w_llp = w_llp.sort_values('Birthrate', ascending=False)
w_llp
| Country | Deathrate | Birthrate | Region | Region_common | brth_dth_diff | diff_color | |
|---|---|---|---|---|---|---|---|
| 151 | Niger | 20.91 | 50.73 | SUB-SAHARAN AFRICA | AFRICA | -29.82 | tab:green |
| 128 | Mali | 16.89 | 49.82 | SUB-SAHARAN AFRICA | AFRICA | -32.93 | tab:green |
| 210 | Uganda | 12.24 | 47.35 | SUB-SAHARAN AFRICA | AFRICA | -35.11 | tab:green |
| 0 | Afghanistan | 20.34 | 46.60 | ASIA (EX. NEAR EAST) | ASIA (EX. NEAR EAST) | -26.26 | tab:green |
| 183 | Sierra Leone | 23.03 | 45.76 | SUB-SAHARAN AFRICA | AFRICA | -22.73 | tab:green |
| ... | ... | ... | ... | ... | ... | ... | ... |
| 101 | Italy | 10.40 | 8.72 | WESTERN EUROPE | EUROPE | 1.68 | tab:red |
| 4 | Andorra | 6.25 | 8.71 | WESTERN EUROPE | EUROPE | -2.46 | tab:green |
| 122 | Macau | 4.47 | 8.48 | ASIA (EX. NEAR EAST) | ASIA (EX. NEAR EAST) | -4.01 | tab:green |
| 76 | Germany | 10.62 | 8.25 | WESTERN EUROPE | EUROPE | 2.37 | tab:red |
| 91 | Hong Kong | 6.29 | 7.29 | ASIA (EX. NEAR EAST) | ASIA (EX. NEAR EAST) | -1.00 | tab:green |
223 rows × 7 columns
plt.figure(figsize=(10, 40))
plt.hlines(data=w_llp, y='Country', xmin='Deathrate', xmax='Birthrate', colors='diff_color') # сначала строим линии
plt.margins(y=0.005) # убираем белые поля
# plt.yticks(np.arange(0, len(w_llp['Country']), 2.0));
plt.scatter(data=w_llp, y='Country', x='Deathrate', color='tab:red', alpha=1, label='Deathrate', s=15)
plt.scatter(data=w_llp, y='Country', x='Birthrate', color='tab:green', alpha=1, label='Birthrate', s=15)
plt.legend()
plt.grid(linestyle='--', alpha=0.5)
plt.title('Difference between birthrate and deathrate\n in countries of the world', size=16, pad=20);
# прошлый график слишком неудобный, поэтому имеет смысл поделить его на части, например, возьмём Европу
w_llp_eu = w_llp[w_llp['Region_common'] == 'EUROPE']
w_llp_eu = w_llp_eu.sort_values('Deathrate', ascending=False)
plt.figure(figsize=(10, 15))
plt.hlines(data=w_llp_eu, y='Country', xmin='Deathrate', xmax='Birthrate', colors='diff_color') # сначала строим линии
plt.margins(y=0.005)
plt.scatter(data=w_llp_eu, y='Country', x='Deathrate', color='tab:red', alpha=1, label='Deathrate', s=20) # добавляем точки
plt.scatter(data=w_llp_eu, y='Country', x='Birthrate', color='tab:green', alpha=1, label='Birthrate', s=20)
plt.legend() # вместо классической легенды можно было бы указать цвета в названии графика
plt.grid(linestyle='--', alpha=0.5)
plt.title('Difference between birthrate and deathrate\n in countries of Europe and former USSR', size=16, pad=20);
sns.despine(left=True, bottom=True) # убираем все границы
plt.tick_params(left=False, bottom=False) # убираем палочки слева и снизу